import { Injectable, Logger } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { PlayerOnlineTimeEntity } from "../entities/player-online-time.entity";

@Injectable()
export class PlayerOnlineTimeService {
  private readonly logger = new Logger(PlayerOnlineTimeService.name);

  constructor(
    @InjectRepository(PlayerOnlineTimeEntity)
    private readonly playerOnlineTimeRepository: Repository<PlayerOnlineTimeEntity>
  ) {}

  /**
   * 记录玩家登录
   * @param characterId 角色ID
   */
  async recordLogin(characterId: number): Promise<void> {
    try {
      const today = this.getTodayDateString();

      // 查找今日记录
      let record = await this.playerOnlineTimeRepository.findOne({
        where: { characterId, date: today },
      });

      if (record) {
        // 如果记录已存在，更新登录时间和在线状态
        record.loginTime = new Date();
        record.isOnline = 1;
        record.lastActivityTime = new Date();
        await this.playerOnlineTimeRepository.save(record);
        this.logger.log(
          `更新角色 ${characterId} 登录时间: ${record.loginTime.toISOString()}`
        );
      } else {
        // 创建新记录
        record = this.playerOnlineTimeRepository.create({
          characterId,
          date: today,
          loginTime: new Date(),
          isOnline: 1,
          totalOnlineMinutes: 0,
          lastActivityTime: new Date(),
        });
        await this.playerOnlineTimeRepository.save(record);
        this.logger.log(`创建角色 ${characterId} 今日在线记录`);
      }
    } catch (error: any) {
      this.logger.error(
        `记录角色 ${characterId} 登录失败:`,
        error?.message || error
      );
    }
  }

  /**
   * 记录玩家离线
   * @param characterId 角色ID
   */
  async recordLogout(characterId: number): Promise<void> {
    try {
      const today = this.getTodayDateString();

      // 查找今日记录
      const record = await this.playerOnlineTimeRepository.findOne({
        where: { characterId, date: today },
      });

      if (record && record.isOnline === 1) {
        const now = new Date();

        // 计算本次在线时长
        const lastActivityTime =
          record.lastActivityTime || record.loginTime || now;
        const sessionMinutes = Math.floor(
          (now.getTime() - lastActivityTime.getTime()) / (1000 * 60)
        );

        // 更新记录
        record.logoutTime = now;
        record.isOnline = 0;
        record.totalOnlineMinutes += Math.max(0, sessionMinutes);
        record.lastActivityTime = now;

        await this.playerOnlineTimeRepository.save(record);
        this.logger.log(
          `记录角色 ${characterId} 离线，本次在线 ${sessionMinutes} 分钟，累计 ${record.totalOnlineMinutes} 分钟`
        );
      }
    } catch (error: any) {
      this.logger.error(
        `记录角色 ${characterId} 离线失败:`,
        error?.message || error
      );
    }
  }

  /**
   * 更新玩家活动时间
   * @param characterId 角色ID
   */
  async updateActivityTime(characterId: number): Promise<void> {
    try {
      const today = this.getTodayDateString();

      // 查找今日记录
      const record = await this.playerOnlineTimeRepository.findOne({
        where: { characterId, date: today, isOnline: 1 },
      });

      if (record) {
        record.lastActivityTime = new Date();
        await this.playerOnlineTimeRepository.save(record);
      }
    } catch (error: any) {
      this.logger.error(
        `更新角色 ${characterId} 活动时间失败:`,
        error?.message || error
      );
    }
  }

  /**
   * 获取玩家今日在线时长（分钟）
   * @param characterId 角色ID
   * @returns 今日在线时长（分钟）
   */
  async getTodayOnlineMinutes(characterId: number): Promise<number> {
    try {
      const today = this.getTodayDateString();

      // 查找今日记录
      const record = await this.playerOnlineTimeRepository.findOne({
        where: { characterId, date: today },
      });

      if (!record) {
        return 0;
      }

      let totalMinutes = record.totalOnlineMinutes;

      // 如果当前在线，需要加上当前会话的时长
      if (record.isOnline === 1 && record.lastActivityTime) {
        const now = new Date();
        const currentSessionMinutes = Math.floor(
          (now.getTime() - record.lastActivityTime.getTime()) / (1000 * 60)
        );
        totalMinutes += Math.max(0, currentSessionMinutes);
      }

      return totalMinutes;
    } catch (error: any) {
      this.logger.error(
        `获取角色 ${characterId} 今日在线时长失败:`,
        error?.message || error
      );
      return 0;
    }
  }

  /**
   * 获取玩家在线状态
   * @param characterId 角色ID
   * @returns 是否在线
   */
  async isPlayerOnline(characterId: number): Promise<boolean> {
    try {
      const today = this.getTodayDateString();

      const record = await this.playerOnlineTimeRepository.findOne({
        where: { characterId, date: today },
      });

      return record ? record.isOnline === 1 : false;
    } catch (error: any) {
      this.logger.error(
        `检查角色 ${characterId} 在线状态失败:`,
        error?.message || error
      );
      return false;
    }
  }

  /**
   * 获取今日日期字符串（YYYY-MM-DD格式）
   * @returns 今日日期字符串
   */
  private getTodayDateString(): string {
    const now = new Date();
    const year = now.getFullYear();
    const month = String(now.getMonth() + 1).padStart(2, "0");
    const day = String(now.getDate()).padStart(2, "0");
    return `${year}-${month}-${day}`;
  }

  /**
   * 清理过期的在线时长记录（保留最近30天）
   */
  async cleanupExpiredRecords(): Promise<number> {
    try {
      const thirtyDaysAgo = new Date();
      thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
      const cutoffDate = thirtyDaysAgo.toISOString().split("T")[0];

      const result = await this.playerOnlineTimeRepository
        .createQueryBuilder()
        .delete()
        .where("date < :cutoffDate", { cutoffDate })
        .execute();

      const deletedCount = result.affected || 0;
      this.logger.log(`清理了 ${deletedCount} 条过期的在线时长记录`);
      return deletedCount;
    } catch (error: any) {
      this.logger.error("清理过期在线时长记录失败:", error?.message || error);
      return 0;
    }
  }

  /**
   * 获取玩家在线时长统计
   * @param characterId 角色ID
   * @param days 统计天数，默认7天
   */
  async getOnlineTimeStats(
    characterId: number,
    days: number = 7
  ): Promise<{
    totalMinutes: number;
    averageMinutes: number;
    records: Array<{
      date: string;
      minutes: number;
      loginTime: Date | null;
      logoutTime: Date | null;
    }>;
  }> {
    try {
      const endDate = new Date();
      const startDate = new Date();
      startDate.setDate(startDate.getDate() - days);

      const records = await this.playerOnlineTimeRepository
        .createQueryBuilder("record")
        .where("record.characterId = :characterId", { characterId })
        .andWhere("record.date >= :startDate", {
          startDate: startDate.toISOString().split("T")[0],
        })
        .andWhere("record.date <= :endDate", {
          endDate: endDate.toISOString().split("T")[0],
        })
        .orderBy("record.date", "DESC")
        .getMany();

      const totalMinutes = records.reduce(
        (sum, record) => sum + record.totalOnlineMinutes,
        0
      );
      const averageMinutes =
        records.length > 0 ? Math.floor(totalMinutes / records.length) : 0;

      return {
        totalMinutes,
        averageMinutes,
        records: records.map((record) => ({
          date: record.date,
          minutes: record.totalOnlineMinutes,
          loginTime: record.loginTime,
          logoutTime: record.logoutTime,
        })),
      };
    } catch (error: any) {
      this.logger.error(
        `获取角色 ${characterId} 在线时长统计失败:`,
        error?.message || error
      );
      return {
        totalMinutes: 0,
        averageMinutes: 0,
        records: [],
      };
    }
  }
}
